// src/fuzzy_matching.cpp
#include "fuzzy_matching.h"
#include <fstream>
#include <sstream>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>

// 全局拼音映射
std::unordered_map<std::string, std::string> pinyin_map;

// // 加载拼音映射文件
// bool load_pinyin_map(const std::string& file_path) {
//     std::ifstream file(file_path, std::ios::in);
//     if (!file.is_open()) {
//         std::cerr << "无法打开拼音映射文件: " << file_path << std::endl;
//         return false;
//     }
//
//     std::string line;
//     while (std::getline(file, line)) {
//         if (line.empty()) continue;
//         size_t colon_pos = line.find(':');
//         if (colon_pos == std::string::npos) continue;
//
//         std::string chinese = line.substr(0, colon_pos);
//         std::string pinyin = line.substr(colon_pos + 1);
//
//         // 去除可能的前后空格
//         chinese.erase(0, chinese.find_first_not_of(" \t"));
//         chinese.erase(chinese.find_last_not_of(" \t") + 1);
//         pinyin.erase(0, pinyin.find_first_not_of(" \t"));
//         pinyin.erase(pinyin.find_last_not_of(" \t") + 1);
//
//         pinyin_map[chinese] = pinyin;
//     }
//
//     file.close();
//     return true;
// }

// 将文本转换为拼音
std::string text_to_pinyin(const std::string& text) {
    std::string pinyin;
    std::string current_word;
    std::stringstream ss(text);

    while (ss >> current_word) {
        for (size_t i = 0; i < current_word.size(); ) {
            unsigned char c = current_word[i];
            size_t char_len = 1;

            // 处理UTF-8字符长度
            if ((c & 0x80) == 0x00) { // ASCII字符
                char_len = 1;
            }
            else if ((c & 0xE0) == 0xC0) { // 2字节字符
                char_len = 2;
            }
            else if ((c & 0xF0) == 0xE0) { // 3字节字符
                char_len = 3;
            }
            else if ((c & 0xF8) == 0xF0) { // 4字节字符
                char_len = 4;
            }

            // 确保不会越界
            if (i + char_len > current_word.size()) {
                pinyin += current_word.substr(i, 1);
                break;
            }

            std::string character = current_word.substr(i, char_len);
            auto it = pinyin_map.find(character);
            if (it != pinyin_map.end()) {
                pinyin += it->second;
            }
            else {
                // 如果没有找到拼音，保持字符原样
                pinyin += character;
            }

            i += char_len;
        }
    }
    return pinyin;
}

// 计算两个拼音字符串的相似度（基于最长公共子序列的比例）
double calculate_similarity(const std::string& pinyin1, const std::string& pinyin2) {
    size_t m = pinyin1.size();
    size_t n = pinyin2.size();
    std::vector<std::vector<size_t>> dp(m + 1, std::vector<size_t>(n + 1, 0));

    for (size_t i = 1; i <= m; ++i) {
        for (size_t j = 1; j <= n; ++j) {
            if (pinyin1[i - 1] == pinyin2[j - 1]) {
                dp[i][j] = dp[i - 1][j - 1] + 1;
            }
            else {
                dp[i][j] = std::max(dp[i - 1][j], dp[i][j - 1]);
            }
        }
    }

    size_t lcs_length = dp[m][n];
    double similarity = 2.0 * lcs_length / (pinyin1.size() + pinyin2.size());
    return similarity;
}

// 计算两个拼音字符串的编辑距离（Levenshtein distance）
int calculate_edit_distance(const std::string& pinyin1, const std::string& pinyin2) {
    size_t m = pinyin1.size();
    size_t n = pinyin2.size();

    // 初始化DP表
    std::vector<std::vector<int>> dp(m + 1, std::vector<int>(n + 1, 0));

    for (size_t i = 0; i <= m; ++i) dp[i][0] = i;
    for (size_t j = 0; j <= n; ++j) dp[0][j] = j;

    for (size_t i = 1; i <= m; ++i) {
        for (size_t j = 1; j <= n; ++j) {
            if (pinyin1[i - 1] == pinyin2[j - 1]) {
                dp[i][j] = dp[i - 1][j - 1];
            }
            else {
                dp[i][j] = 1 + std::min({ dp[i - 1][j],    // 删除
                                          dp[i][j - 1],    // 插入
                                          dp[i - 1][j - 1] // 替换
                    });
            }
        }
    }

    return dp[m][n];
}

// 判断是否匹配
bool is_match(const std::string& original_text, const std::string& recognized_text,
    double similarity_threshold, int max_edit_distance, double max_length_diff_ratio) {
    // 转换为拼音
    std::string original_pinyin = text_to_pinyin(original_text);
    std::string recognized_pinyin = text_to_pinyin(recognized_text);

    // 计算拼音相似度
    double pinyin_similarity = calculate_similarity(original_pinyin, recognized_pinyin);
    if (pinyin_similarity < similarity_threshold) {
        return false;
    }

    // 计算编辑距离
    int edit_distance = calculate_edit_distance(original_pinyin, recognized_pinyin);
    if (edit_distance > max_edit_distance) {
        return false;
    }

    // 计算长度差异比例
    double length_diff_ratio = 0.0;
    if (!original_pinyin.empty()) {
        length_diff_ratio = std::abs(static_cast<int>(original_pinyin.size()) -
            static_cast<int>(recognized_pinyin.size())) /
            static_cast<double>(original_pinyin.size());
    }

    if (length_diff_ratio > max_length_diff_ratio) {
        return false;
    }

    return true;
}

// 加载拼音映射文件
bool load_pinyin_map(const std::string& file_path) {
    std::string input_text = "清: qing\n晨: chen\n，: ，\n当: dang\n第: di\n一: yi\n缕: lv\n阳: yang\n光: guang\n穿: chuan\n透: tou\n云: yun\n层: ceng\n洒: sa\n向: xiang\n大: da\n地: di\n时: shi\n世: shi\n界: jie\n仿: fang\n佛: fu\n被: bei\n点: dian\n亮: liang\n了: le\n般: ban\n充: chong\n满: man\n生: sheng\n机: ji\n和: he\n希: xi\n望: wang\n我: wo\n推: tui\n开: kai\n窗: chuang\n户: hu\n深: shen\n吸: xi\n口: kou\n新: xin\n的: de\n空: kong\n气: qi\n感: gan\n受: shou\n到: dao\n自: zi\n然: ran\n美: mei\n好: hao\n这: zhe\n样: yang\n早: zao\n总: zong\n能: neng\n让: rang\n人: ren\n活: huo\n力: li\n今: jin\n天: tian\n计: ji\n划: hua\n是: shi\n去: qu\n附: fu\n近: jin\n森: sen\n林: lin\n公: gong\n园: yuan\n徒: tu\n步: bu\n享: xiang\n宁: ning\n静: jing\n丽: li\n里: li\n树: shu\n木: mu\n郁: yu\n葱: cong\n中: zhong\n弥: mi\n漫: man\n着: zhe\n淡: dan\n花: hua\n香: xiang\n鸟: niao\n儿: er\n在: zai\n梢: shao\n间: jian\n欢: huan\n快: kuai\n歌: ge\n唱: chang\n似: shi\n乎: hu\n迎: ying\n每: mei\n位: wei\n来: lai\n沿: yan\n蜿: wan\n蜒: yan\n小: xiao\n路: lu\n边: bian\n慢: man\n行: xing\n走: zou\n欣: xin\n赏: shang\n周: zhou\n围: wei\n风: feng\n景: jing\n过: guo\n叶: ye\n上: shang\n形: xing\n成: cheng\n斑: ban\n驳: bo\n影: ying\n溪: xi\n水: shui\n潺: chan\n流: liu\n澈: che\n见: jian\n底: jian\n映: ying\n衬: chen\n蓝: lan\n绿: lv\n累: lei\n坐: zuo\n块: kuai\n石: shi\n头: tou\n聆: ling\n听: ting\n声: sheng\n音: yin\n片: pian\n刻: ke\n回: hui\n家: jia\n后: hou\n始: shi\n阅: yue\n读: du\n本: ben\n关: guan\n于: yu\n工: gong\n智: zhi\n书: shu\n入: ru\n浅: qian\n出: chu\n介: jie\n绍: shou\n发: fa\n展: zhan\n历: li\n史: shi\n、: 、\n核: he\n心: xin\n技: ji\n术: shu\n以: yi\n及: ji\n未: wei\n应: ying\n用: yong\n场: chang\n已: yi\n经: jing\n许: xu\n多: duo\n领: ling\n域: yu\n取: qu\n得: de\n显: xian\n著: zhu\n果: guo\n比: bi\n如: ru\n医: yi\n疗: liao\n教: jiao\n育: yu\n交: jiao\n通: tong\n金: jin\n融: rong\n等: deng\n可: ke\n帮: bang\n助: zhu\n诊: zhen\n断: duan\n疾: ji\n病: bing\n提: ti\n供: gong\n个: ge\n性: xing\n化: hua\n治: zhi\n方: fang\n案: an\n根: gen\n据: ju\n学: xue\n习: xi\n情: qing\n况: kuang\n针: zhen\n对: dui\n辅: fu\n导: dao\n无: wu\n驾: jia\n驶: shi\n正: zheng\n逐: zhu\n实: shi\n现: xian\n为: wei\n们: men\n便: bian\n利: li\n够: gou\n分: fen\n析: xi\n海: hai\n量: liang\n数: shu\n投: tou\n资: zi\n者: zhe\n做: zuo\n更: geng\n明: ming\n决: jue\n策: ce\n而: er\n也: ye\n伴: ban\n随: sui\n些: xie\n挑: zhan\n战: zhan\n隐: yin\n私: si\n问: wen\n题: ti\n伦: lun\n理: li\n道: dao\n德: de\n潜: qian\n安: an\n安全: quan\n险: xian\n何: he\n同: tong\n确: que\n保: bao\n控: kong\n需: xu\n要: yao\n共: gong\n面: mian\n重: zhong\n课: ke\n思: si\n考: kao\n不: bu\n禁: jin\n期: qi\n待: dai\n担: dan\n忧: you\n下: xia\n午: wu\n博: bo\n物: wu\n馆: guan\n参: can\n观: guan\n古: gu\n代: dai\n文: wen\n览: lan\n示: shi\n珍: zhen\n贵: gui\n青: qing\n铜: tong\n器: qi\n陶: tao\n法: fa\n绘: hui\n画: hua\n仅: jin\n象: xiang\n征: zheng\n解: jie\n件: jian\n精: jing\n印: yin\n它: ta\n纹: wen\n饰: shi\n复: fu\n杂: za\n匠: jiang\n慧: hui\n艺: yi\n还: hai\n社: she\n会: hui\n科: ke\n知: zhi\n识: shi\n四: si\n响: xiang\n丝: si\n绸: chou\n之: zhi\n促: cu\n进: jin\n东: dong\n西: xi\n民: min\n族: zu\n记: ji\n忆: yi\n类: lei\n组: zu\n部: bu\n从: cong\n汲: ji\n反: fan\n借: jie\n鉴: jian\n那: na\n句: ju\n话: hua\n所: suo\n说: shuo\n：: ：\n“: “\n兴: xing\n替: ti\n”: ”\n字: zi\n基: ji\n搜: sou\n冷: leng\n传: chuan\n承: cheng\n晚: wan\n起: qi\n厨: chu\n房: fang\n饭: fan\n最: zui\n放: fang\n松: song\n增: zeng\n合: he\n作: zuo\n有: you\n负: fu\n责: ze\n切: qie\n菜: cai\n炒: chao\n摆: bai\n盘: pan\n单: dan\n包: bao\n括: kuo\n红: hong\n烧: shao\n鱼: yu\n宫: gong\n鸡: ji\n丁: ding\n蔬: shu\n锅: guo\n热: re\n腾: teng\n汤: tang\n整: zheng\n食: shi\n欲: yu\n聊: liao\n很: hen\n趣: qu\n闻: wen\n琐: suo\n事: shi\n谈: tan\n种: zhong\n平: ping\n凡: fan\n温: wen\n暖: nuan\n国: guo\n拥: yong\n悠: you\n久: jiu\n灿: can\n烂: lan\n诗: shi\n词: ci\n赋: fu\n创: chuang\n终: zhong\n勤: qin\n劳: lao\n动: dong\n《: 《\n》: 》\n楚: chu\n辞: ci\n录: lu\n与: yu\n唐: tang\n宋: song\n则: ze\n达: da\n典: dian\n巅: dian\n峰: feng\n改: gai\n变: bian\n产: chan\n远: yuan\n子: zi\n算: suan\n航: hang\n程: cheng\n就: jiu\n令: ling\n瞩: zhu\n目: mu\n强: qiang\n采: cai\n节: jie\n假: jia\n日: ri\n候: hou\n喜: xi\n旅: lv\n身: shen\n式: shi\n长: zhang\n拓: tuo\n视: shi\n野: ye\n年: nian\n南: nan\n江: jiang\n两: liang\n其: qi\n独: du\n特: te\n引: yin\n游: you\n客: ke\n苍: cang\n山: shan\n洱: er\n高: gao\n原: yuan\n湖: hu\n泊: po\n壮: zhuang\n城: cheng\n巷: xiang\n统: tong\n纳: na\n建: jian\n筑: zhu\n品: pin\n尝: chang\n色: se\n桥: qiao\n米: mi\n线: xian\n鲜: xian\n饼: bing\n味: wei\n难: nan\n忘: wang\n宇: yu\n宙: zhou\n探: tan\n索: suo\n浩: hao\n瀚: han\n神: shen\n秘: mi\n敬: jing\n畏: wei\n银: yin\n河: he\n系: xi\n结: jie\n构: gou\n黑: hei\n洞: dong\n演: yan\n追: zhui\n溯: su\n1: 1\n3: 3\n8: 8\n亿: yi\n前: qian\n爆: bao\n炸: zha\n颗: ke\n星: xing\n都: dou\n己: ji\n故: gu\n测: ce\n研: yan\n究: jiu\n揭: jie\n奥: ao\n魅: mei\n穷: qiong\n尽: jin\n答: da\n带: dai\n速: su\n手: shou\n太: tai\n源: yuan\n塑: su\n任: ren\n求: qiu\n注: zhu\n环: huan\n境: jing\n护: hu\n球: qiu\n持: chi\n续: xu\n贡: gong\n献: xian\n像: xiang\n途: tu\n论: lun\n遇: yu\n什: shen\n么: me\n困: kun\n只: zhi\n积: ji\n极: ji\n乐: le\n态: tai\n找: zhao\n办: ban\n属: shu\n幸: xing\n福: fu\n意: yi\n义: yi\n雨: yu\n爱: ai\n朵: duo";
    std::istringstream iss(input_text);
    std::string line;
    while (std::getline(iss, line)) {
        std::size_t pos = line.find(':');
        if (pos!= std::string::npos) {
            std::string chinese_char = line.substr(0, pos);
            std::string pinyin = line.substr(pos + 1);
            pinyin_map[chinese_char] = pinyin;
        }
    }
    return true;
}

/*---------------------测试中文是否乱码---------------------*/
// 拼音映射文件转化为string
std::string mapToString(const std::unordered_map<std::string, std::string>& inputMap) {
    std::stringstream ss;
    for (const auto& pair : inputMap) {
        ss << pair.first << ":" << pair.second << ";";  // 这里以":"隔开键值，以";"隔开不同键值对，可按需调整格式
    }
    return ss.str();
}

// 显示拼音映射文件
std::string show(){
    return mapToString(pinyin_map);
}

// 测试中文是否正常显示
std::string test() {
    std::string input_text = "清: qing\n晨: chen";
    std::istringstream iss(input_text);
    std::string line;
    while (std::getline(iss, line)) {
        std::size_t pos = line.find(':');
        if (pos!= std::string::npos) {
            std::string chinese_char = line.substr(0, pos);
            std::string pinyin = line.substr(pos + 1);
            pinyin_map[chinese_char] = pinyin;
        }
    }
    return input_text;
}
/*---------------------测试中文是否乱码---------------------*/